package com.hxzy.common.config.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hxzy.common.enums.AckCode;
import com.hxzy.common.properties.TokenProperty;
import com.hxzy.common.util.SecurityContextUtil;
import com.hxzy.common.util.TokenUtil;
import com.hxzy.common.vo.resp.R;
import com.hxzy.controller.admin.vo.resp.AdminLoginResp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 功能描述:后端令牌拦截器
 *
 * @author tonneyyy
 */
@Component
public class AdminTokenInterceptor implements HandlerInterceptor {

    @Autowired
    private TokenProperty  tokenProperty;

    @Autowired
    private TokenUtil tokenUtil;

    /**
     * 执行Controller方法之前操作
     * 1、获取请求头的key
     * 2、如果有，jwt验证有效性
     * 3、如果没有问题，判断令牌剩余时间<=配置刷新令牌时间，更新redis缓存时间(续时)
     * 4、把当前登录对象存放到本地线程池ThreadLocal中，供后面方法使用
     *    如果并发量很大，使用阿里的TransmittableThreadLocal线程池
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         //1、获取令牌信息
        String jwtToken=request.getHeader(this.tokenProperty.getAdminHeader());
        //2、判断令牌是否有值
        if(StrUtil.isBlank(jwtToken)){
            R r=R.build(AckCode.TOKEN_NOT_BLANK);
            //输出r
            out(response,r);
            return false;
        }

        //3、验证令牌有效性
        AdminLoginResp  adminLoginResp=this.tokenUtil.veritifyToken(jwtToken);

        //4、判断是否(刷新令牌)续时
        if(this.tokenProperty.getAutoRefreshToken()) {
            this.tokenUtil.refreshToken(adminLoginResp);
        }
        //5、把当前用户存起来，给后面的线程使用
        SecurityContextUtil.setAdminUser(adminLoginResp);

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        SecurityContextUtil.removeAdminUser();
    }

    /**
     * 数据输出给前端
     * @param response
     * @param r
     * @throws IOException
     */
    private void out(HttpServletResponse response,R r) throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        String json= JSONUtil.toJsonStr(r);
        try(PrintWriter writer = response.getWriter()) {
            writer.println(json);
            writer.flush();
        }
    }
}
